package bancosys.tec.services.implementor.annotations.visitor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Member;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;

import jmine.tec.di.cache.TypeMatchLookup;
import jmine.tec.di.metadata.DependencyMetaData;
import jmine.tec.di.metadata.impl.DependencyMetaDataImpl;
import jmine.tec.di.resolver.impl.RegexMatchingResolver;
import jmine.tec.di.type.NoTypeConverter;
import jmine.tec.di.type.TypeConverter;
import jmine.tec.di.wrapper.Wrappers;
import jmine.tec.services.annotations.WithRegex;
import jmine.tec.utils.Tuple;

/**
 * AnnotationVisitor para {@link WithRegex}
 * 
 * @author takeshi
 */
public class WithRegexAnnotationVisitor extends SetterAndParametersAnnotationVisitor<DependencyMetaData> {
    private final TypeMatchLookup<TypeConverter<?>> typeConverters;

    /**
     * C'tor
     * 
     * @param typeConverters o sistema de conversao de tipos
     */
    public WithRegexAnnotationVisitor(TypeMatchLookup<TypeConverter<?>> typeConverters) {
        super(WithRegex.class);
        this.typeConverters = typeConverters;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected Collection<? extends DependencyMetaData> onPropertySetterAnnotation(Annotation annotation, Class<?> declaringClass,
            String propertyName, Class<?> propertyRawType, Type generictType) {
        WithRegex regex = (WithRegex) annotation;
        Tuple<Class<?>, Class<?>> tuple = SuffixOfAnnotationVisitor.extractKeyAndValueTypes(propertyRawType, generictType);
        TypeConverter<?> keyTypeConverter = this.typeConverters.lookup(tuple.head(), NoTypeConverter.getInstance());
        TypeConverter<?> valueTypeConverter = this.typeConverters.lookup(tuple.tail(), NoTypeConverter.getInstance());
        return Collections.singleton(new DependencyMetaDataImpl("regex: " + regex, new RegexMatchingResolver(tuple.tail(), regex.regex(),
                valueTypeConverter, regex.groupIndex(), tuple.head(), keyTypeConverter), false, Wrappers.findWrapperFor(propertyRawType),
                tuple.tail()));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected Collection<? extends DependencyMetaData> onParameterAnnotation(Annotation annotation, Class<?> annotated, int parameterIndex,
            Class<?> parameterType, Type genericType, Member annotatedMember) {
        WithRegex regex = (WithRegex) annotation;
        return this.onPropertySetterAnnotation(regex, annotated, "regex: " + regex.regex(), parameterType, genericType);
    }

}
